home *** CD-ROM | disk | FTP | other *** search
/ Language/OS - Multiplatform Resource Library / LANGUAGE OS.iso / cpp_libs / utility.lha / utility / list.C < prev    next >
C/C++ Source or Header  |  1993-08-08  |  6KB  |  327 lines

  1. /////////////////////////////////////////////////////////////////////
  2. //
  3. // list.C
  4. // 
  5. // Package for lists using dynamic arrays.  Allows an element to be
  6. // member of multiple lists simultaneously.
  7. //
  8. // Author:
  9. //
  10. // Dag Bruck, Department of Automatic Control, Lund Institute of Technology,
  11. // Box 118, S-221 00 Lund, Sweden (dag@control.lth.se).
  12. //
  13. // History:
  14. //
  15. // 1987-10-28  DB  First version.
  16. // 1989-07-14  DB  Total reimplementation.
  17. // 1990-02-02  DB  Implemented Remove()!
  18. // 1991-09-06  DB  Changed to pool allocation of small lists.
  19. /////////////////////////////////////////////////////////////////////
  20. //
  21. // $Id: list.C,v 1.4 91/09/06 18:19:05 dag Exp $
  22.  
  23.  
  24.  
  25. #include <list.H>
  26. #include <defs.H>
  27. #include <stdlib.h>
  28. #include <pool.H>
  29. #include <statcount.H>
  30.  
  31.  
  32. const int CHUNK_SIZE = 16;
  33.  
  34.  
  35. ////////////////////////////////////////////////////////////////////
  36. //
  37. // Helper functions for pool management.
  38. //
  39.  
  40.  
  41. static Pool* pool;        // zeroed by default in UNIX
  42.  
  43.  
  44. inline Pointer* alloc_list(unsigned size)
  45. {
  46. #if 0
  47.   static StatCount cnt("Distribution of list allocation:", 0, 200, 4);
  48.   cnt(size);
  49. #endif
  50.  
  51.   if (pool == nil) pool = new Pool(CHUNK_SIZE * sizeof(Pointer));
  52.   
  53.   return size == CHUNK_SIZE ? (Pointer *) pool->alloc() : new Pointer[size];
  54. }
  55.  
  56.  
  57. inline void free_list(Pointer* p, unsigned size)
  58. {
  59.   if (size == CHUNK_SIZE)
  60.     pool->free(p);
  61.   else
  62.     delete [] p;
  63. }
  64.  
  65.  
  66. ////////////////////////////////////////////////////////////////////
  67. //
  68. // Copy pointer array efficiently.
  69. //
  70.  
  71. inline void copyarray(register Pointer* dst, const register Pointer* src,
  72.               register int n)
  73. {
  74.   while (--n >= 0)
  75.     *(dst++) = *(src++);
  76. }
  77.  
  78.  
  79. ////////////////////////////////////////////////////////////////////
  80. //
  81. // Constructors and destructors for generic list.
  82. //
  83.  
  84. GenericList :: GenericList()
  85.     : n(0), size(CHUNK_SIZE)
  86. {
  87.   p = alloc_list(size);
  88. }
  89.  
  90.  
  91. GenericList :: GenericList(const GenericList& l)
  92.     : n(l.n), size(l.size)
  93. {
  94.   p = alloc_list(size);
  95.   copyarray(p, l.p, n);
  96. }
  97.  
  98.  
  99. GenericList :: ~GenericList()
  100. {
  101.   free_list(p, size);
  102. }
  103.  
  104.  
  105. ///////////////////////////////////////////////////////////////////
  106. //
  107. // Assignment.
  108. //
  109.  
  110.  
  111. void GenericList :: operator = (const GenericList& l)
  112. {
  113.   if (this == &l)        // x = x;
  114.     return;
  115.  
  116.   n = l.n;
  117.   if (size < n) {
  118.     free_list(p, size);
  119.     size = l.size;
  120.     p = alloc_list(size);
  121.   }
  122.   copyarray(p, l.p, n);
  123. }
  124.  
  125.  
  126. ///////////////////////////////////////////////////////////////////
  127. //
  128. // Insert element into list (first and last).
  129. //
  130.  
  131. void GenericList :: Insert(Pointer e)
  132. {
  133.   if (e == nil)            // no-op
  134.     return;
  135.   
  136.   if (n == size)
  137.     Expand();
  138.   p[n++] = e;
  139. }
  140.  
  141.  
  142. void GenericList :: Append(Pointer e)
  143. {
  144.   if (e == nil)            // no-op
  145.     return;
  146.   
  147.   if (n == size)
  148.     Expand();
  149.   for (register int i = n; i > 0; i--)
  150.     p[i] = p[i-1];
  151.   p[0] = e;
  152.   n++;
  153. }
  154.  
  155.  
  156. ///////////////////////////////////////////////////////////////////
  157. //
  158. // Append list
  159. //
  160.  
  161.  
  162. void GenericList :: Append(const GenericList& l)
  163. {
  164.   if (l.n == 0)            // no-op
  165.     return;
  166.   
  167.   unsigned new_n = n + l.n;
  168.   if (new_n < size) {        // existing array is big enough
  169.     for (register int i = n-1; i >= 0; i--)
  170.       p[i + l.n] = p[i];
  171.     copyarray(p, l.p, l.n);
  172.     n = new_n;
  173.   }
  174.   else {            // must allocate bigger array
  175.     unsigned new_size = CHUNK_SIZE * ((new_n+CHUNK_SIZE-1) / CHUNK_SIZE);
  176.     // round up to multiple of CHUNK_SIZE
  177.     Pointer* new_p = alloc_list(new_size);
  178.  
  179.     copyarray(new_p, l.p, l.n);
  180.     copyarray(new_p + l.n, p, n);
  181.  
  182.     free_list(p, size);
  183.     p = new_p;
  184.     size = new_size;
  185.     n = new_n;
  186.   }
  187. }
  188.  
  189.  
  190. ///////////////////////////////////////////////////////////////////
  191. //
  192. // Some more operations on lists: Remove, Member, Replace, Reverse.
  193. //
  194.  
  195.  
  196. void GenericList :: Remove(Pointer e)
  197. {
  198.   if (n == 0 || e == nil)    // no-op
  199.     return;
  200.   else if (p[n-1] == e)        // simple case
  201.     n--;
  202.   else {
  203.     register int i = 0;
  204.     while (i < n && p[i] != e)
  205.       i++;
  206.     if (i < n) {        // did we find element?
  207.       while (i < n) {
  208.     p[i] = p[i+1];
  209.     i++;
  210.       }
  211.       n--;
  212.     }
  213.   }
  214. }
  215.  
  216.  
  217. void GenericList :: RemoveAll()
  218. {
  219.   n = 0;
  220. }
  221.  
  222.  
  223. boolean GenericList :: Member(register Pointer e) const
  224. {
  225.   register int i = n;
  226.   register Pointer* q = p;
  227.   while (--i >= 0)
  228.     if (*(q++) == e) return true;
  229.  
  230.   return false;
  231. }
  232.  
  233.  
  234. void GenericList :: Replace(register Pointer old_e, Pointer new_e)
  235. {
  236.   register int i = n;
  237.   register Pointer* q = p;
  238.   while (--i >= 0) {
  239.     if (*q == old_e)
  240.       *q = new_e;
  241.     q++;
  242.   }
  243. }
  244.  
  245.  
  246. void GenericList :: Reverse()
  247. {
  248.   register int i = n / 2;
  249.   register Pointer* q1 = p;    // first
  250.   register Pointer* q2 = p+n-1;    // last
  251.   
  252.   while (--i >= 0) {
  253.     register Pointer t = *q1;
  254.     *(q1++) = *q2;
  255.     *(q2--) = t;
  256.   }
  257. }
  258.  
  259.  
  260. ///////////////////////////////////////////////////////////////////
  261. //
  262. // Return first, second, third, fourth, fifth, i:th and last elements of list.
  263. //
  264.  
  265.  
  266. Pointer GenericList :: First() const
  267. {
  268.   return n < 1 ? nil : p[n-1];
  269. }
  270.  
  271.  
  272. Pointer GenericList :: Second() const
  273. {
  274.   return n < 2 ? nil : p[n-2];
  275. }
  276.  
  277.  
  278. Pointer GenericList :: Third() const
  279. {
  280.   return n < 3 ? nil : p[n-3];
  281. }
  282.  
  283.  
  284. Pointer GenericList :: Fourth() const
  285. {
  286.   return n < 4 ? nil : p[n-4];
  287. }
  288.  
  289.  
  290. Pointer GenericList :: Fifth() const
  291. {
  292.   return n < 5 ? nil : p[n-5];
  293. }
  294.  
  295.  
  296. Pointer GenericList :: Nth(const int i) const
  297. {
  298.   return i < 1 || n < i ? nil : p[n-i];
  299. }
  300.  
  301.  
  302. Pointer GenericList :: Last() const
  303. {
  304.   if (n == 0)
  305.     return nil;
  306.   else
  307.     return p[0];
  308. }
  309.  
  310.  
  311. ///////////////////////////////////////////////////////////////////
  312. //
  313. // Expand pointer array (copying contents).
  314. //
  315.  
  316.  
  317. void GenericList :: Expand()
  318. {
  319.   unsigned new_size = size + CHUNK_SIZE;
  320.   Pointer* new_p = alloc_list(new_size);
  321.   copyarray(new_p, p, n);
  322.  
  323.   free_list(p, size);
  324.   p = new_p;
  325.   size = new_size;
  326. }
  327.